#include "Thread.h"
#include "TimeWaiter.h"

TimeWaiter::TimeWaiter(void)
{
	m_mutex = new pthread_mutex_t;
	memset(m_mutex, 0, sizeof(pthread_mutex_t));
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(m_mutex, &attr);
	pthread_mutexattr_destroy(&attr);

	m_cond = new pthread_cond_t;
	memset(m_cond, 0, sizeof(m_cond));
	pthread_cond_init(m_cond, NULL);
	m_wait = false;
}

TimeWaiter::~TimeWaiter(void)
{
	CancelWait();
	pthread_mutex_lock(m_mutex); //remove it avoid to app will be hang when closing it.
	pthread_cond_signal(m_cond);
	pthread_cond_destroy(m_cond);
	SAFE_DELETE(m_cond);
	pthread_mutex_unlock(m_mutex);//remove it avoid to app will be hang when closing it.
	pthread_mutex_destroy(m_mutex);
	SAFE_DELETE(m_mutex);
}

void TimeWaiter::SyncWait(long t)
{
	pthread_mutex_lock(m_mutex);
	time_t tt;
	time(&tt);
	timespec tspec;
	tspec.tv_sec = t + tt;
	tspec.tv_nsec = 0;
	m_wait = true;
	pthread_cleanup_push(cleanup_mutex, this);
	pthread_cond_timedwait(m_cond, m_mutex, &tspec);
	pthread_cleanup_pop(0);
	pthread_mutex_unlock(m_mutex);
}

void TimeWaiter::CancelWait()
{
	pthread_cond_signal(m_cond);
	m_wait = false;
}

bool TimeWaiter::IsWaiting()
{
	return m_wait;
}

#ifdef _WINDOWS
void* TimeWaiter::cleanup_mutex(void* param)
#else
void TimeWaiter::cleanup_mutex(void* param)
#endif
{
	TimeWaiter* waiter = (TimeWaiter*)param;
	waiter->m_wait = false;
	pthread_mutex_unlock(waiter->m_mutex);
#ifdef _WINDOWS
	return 0;
#else
	return;
#endif
}
